package com.example.cc.client.initializer;

import cn.hutool.core.util.IdUtil;
import com.example.cc.client.properties.ConfigCenterProperties;
import com.example.cc.common.rabbitmq.RabbitConstants;
import lombok.extern.slf4j.Slf4j;
import org.springframework.amqp.core.Binding;
import org.springframework.amqp.core.BindingBuilder;
import org.springframework.amqp.core.Queue;
import org.springframework.amqp.core.TopicExchange;
import org.springframework.amqp.rabbit.connection.ConnectionFactory;
import org.springframework.amqp.rabbit.core.RabbitAdmin;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;

import java.net.InetAddress;
import java.net.UnknownHostException;

/**
 * 客户端自己负责队列及绑定key的创建逻辑，这样可以灵活控制队列和绑定key的命名策略
 */
@Component
@Slf4j
public class QueueInitializer {

    private final ConfigCenterProperties configCenterProperties;
    private final ConnectionFactory connectionFactory;

    @Value("${queue.name.strategy:uuid}")
    private String queueStrategy;

    @Autowired
    public QueueInitializer(ConfigCenterProperties configCenterProperties,
                            ConnectionFactory connectionFactory) {
        this.configCenterProperties = configCenterProperties;
        this.connectionFactory = connectionFactory;
    }

    public Queue createQueue() {
        String clientId = configCenterProperties.getClientId() + "-" + getUniqueId();
        Queue queue = new Queue(RabbitConstants.CLIENT_QUEUE_PREFIX + clientId, true, false, true); // durable queue
        RabbitAdmin rabbitAdmin = new RabbitAdmin(connectionFactory);
        rabbitAdmin.declareQueue(queue);
        return queue;
    }

    public Binding bindQueueToExchange(Queue queue) {
        String clientId = configCenterProperties.getClientId();
        // String clientId = queue.getName().replace(RabbitMqConstants.CLIENT_QUEUE_PREFIX, "");
        String bindingKey = clientId + ".#";
        Binding binding = BindingBuilder.bind(queue)
                .to(new TopicExchange(RabbitConstants.EXCHANGE_NAME, true, false))
                .with(bindingKey);
        RabbitAdmin rabbitAdmin = new RabbitAdmin(connectionFactory);
        rabbitAdmin.declareBinding(binding);
        return binding;
    }

    private String getUniqueId() {
        switch (queueStrategy.toLowerCase()) {
            case "instance-id":
                return getInstanceId();
            case "uuid":
                return IdUtil.fastSimpleUUID();
            case "host":
            default:
                return getHostName();
        }
    }

    private String getInstanceId() {
        // 尝试从环境变量获取实例ID
        String instanceId = System.getenv("INSTANCE_ID");
        if (instanceId == null || instanceId.isEmpty()) {
            throw new IllegalStateException("Environment variable INSTANCE_ID is not set.");
        }
        return instanceId;
    }

    private String getHostName() {
        try {
            InetAddress addr = InetAddress.getLocalHost();
            // return addr.getHostName();
            return addr.getHostAddress().replace(".", "-");
        } catch (UnknownHostException e) {
            throw new RuntimeException("Failed to obtain host name or IP address.", e);
        }
    }
}
